/** @file
@brief Declarations related to #PrynResult. */
#ifndef PRYN_RESULT_H
#define PRYN_RESULT_H

/** A result code from a Pryn API function call. Zero or positive are success codes; negative are error codes.

	The result code's composed of several discrete parts. The type discriminates between success and failure codes. The code tells you what the result is, from errors to false, and is combined with the type to indicate the result. The options field is dependent on the code. The source field indicates which system returned the result, such as #PrynResultSourcePin. The function field indicates which function returned the result, such as #prynPinCreate. Combining the source field with the function field uniquely identifies a function.

	@ingroup PrynResult
*/
typedef enum PrynResult PrynResult;
typedef struct PrynException PrynException;
struct PrynState;

/** @defgroup PrynResult PrynResult C API
	@{
	@}
*/

enum PrynResult
{
	PrynResultSuccess = 0, ///< Normal success code.
	PrynResultTrue = 0, ///< For a function with a boolean true/false result, this indicates true while #PrynResultFalse indicates false. Note this is the same numeric value as #PrynResultSuccess, and that it is zero, not non-zero.
	PrynResultDone = 1, ///< Some task has been completed. For example, an iterator will return this when iteration is complete.
	PrynResultFalse = 1, ///< For a function with a boolean true/false result, this indicates false while #PrynResultTrue indicates true. Note this is the same numeric value as #PrynResultDone.
	PrynResultStreamNotAllRead = 2, ///< #prynStreamRead didn't read all the bytes requested.
	PrynResultStreamNotAllWritten = 3, ///< #prynStreamWrite didn't write all the bytes requested.
	
	PrynResultFailure = -1, ///< General failure.
	PrynResultOutOfMemory = -2, ///< A memory allocation failed. This should indicate that memory has been exhausted; but sometimes it could be because the program has run off the rails and tried an invalid allocation.
	PrynResultNullArgument = -3, ///< An argument which cannot be null was.
	PrynResultBadArgument = -4, ///< An argument had an invalid value.
	PrynResultUnknownEnumeration = -7, ///< An enumeration parameter has an unknown or unimplemented value. This may happen if a client is of a newer version than the Pryn binary.
	PrynResultIdNotFound = -5, ///< An identifier was searched for but not found.
	PrynResultUnimplemented = -6, ///< The operation appears to be fine, but the function is not implemented.
	PrynResultFileNotFound = -8, ///< An attempt was made to use a file that doesn't appear to exist.
	PrynResultStreamReadFailure  = -9, ///< A stream was read from, but it couldn't read the number of bytes requested. This is only returned from #prynStreamReadExact. #prynStreamRead returns #PrynResultStreamNotAllRead in the same condition.
	PrynResultStreamWriteFailure = -10, ///< A stream was written to, but it couldn't write the number of bytes requested. This is only returned from #prynStreamWriteExact. #prynStreamWrite returns #PrynResultStreamNotAllWritten in the same condition.
	PrynResultExternalFailure = -11, ///< An external function such as a Windows or Linux API function failed in an unknown way.
	PrynResultIncompatibleStates = -12, ///< Two arguments came from two different, incompatible states.
	
	PrynResultFailureMask = 1 << 31, ///< A bit that, if set, indicates a failure condition.

	PrynResultCodeBits = 8, ///< The number of bits in the code field.
	PrynResultCodeShift = 0, ///< The shift to the left that gives a code field.
	PrynResultCodeMask = (((1 << PrynResultCodeBits) - 1) << PrynResultCodeShift) | PrynResultFailureMask, ///< A mask that isolates the condition code, including the failure bit.

	PrynResultOptionsBits = 8, ///< The number of bits in the option field.
	PrynResultOptionsShift = PrynResultCodeBits + PrynResultCodeShift, ///< The shift for values in the option field.
	PrynResultOptionsMask = (((1 << PrynResultOptionsBits) - 1) << PrynResultOptionsShift), ///< A mask that isolates the options field.

	PrynResultSourceBits = 7, ///< The number of bits in the source field.
	PrynResultSourceShift = PrynResultOptionsBits + PrynResultOptionsShift, ///< The shift for values in the source field.
	PrynResultSourceMask = ((1 << PrynResultSourceBits) - 1) << PrynResultSourceShift, ///< A mask that isolates the source field.

	PrynResultSourceGeneral = 0 << PrynResultSourceShift, ///< Source value for a function that doesn't fit into any other slot.
	PrynResultSourceChange = 1 << PrynResultSourceShift, ///< Source value for a #PrynChange-related function.
	PrynResultSourceComponent = 2 << PrynResultSourceShift, ///< Source value for a #PrynComponent-related function.
	PrynResultSourceFactory = 3 << PrynResultSourceShift, ///< Source value for a #PrynFactory-related function.
	PrynResultSourceLibrary = 4 << PrynResultSourceShift, ///< Source value for a #PrynLibrary-related function.
	PrynResultSourceMediator = 5 << PrynResultSourceShift, ///< Source value for a #PrynMediator-related function.
	PrynResultSourceMonitor = 6 << PrynResultSourceShift, ///< Source value for a #PrynMonitor-related function.
	PrynResultSourceObject = 7 << PrynResultSourceShift, ///< Source value for a #PrynObject-related function.
	PrynResultSourcePin = 8 << PrynResultSourceShift, ///< Source value for a #PrynPin-related function.
	PrynResultSourceState = 9 << PrynResultSourceShift, ///< Source value for a #PrynState-related function.
	PrynResultSourceStream = 10 << PrynResultSourceShift, ///< Source value for a #PrynStream-related function.
	PrynResultSourceString = 11 << PrynResultSourceShift, ///< Source value for a #PrynString-related function.
	PrynResultSourceTag = 12 << PrynResultSourceShift, ///< Source value for a #PrynTag-related function.
	PrynResultSourceType = 13 << PrynResultSourceShift, ///< Source value for a #PrynType-related function.
	PrynResultSourceValue = 14 << PrynResultSourceShift, ///< Source value for a #PrynValue-related function.
	// Next value: 15

	PrynResultFunctionBits = 8, ///< The number of bits in the function field.
	PrynResultFunctionShift = PrynResultSourceBits + PrynResultSourceShift, ///< The shift for values in the function field.
	PrynResultFunctionMask = (((1 << PrynResultFunctionBits) - 1) << PrynResultFunctionShift), ///< A mask that isolates the function field.

	PrynResultFunctionGeneral = 0 << PrynResultFunctionShift, ///< A function code for a general function, as in one that doesn't yet have a specific value.

	#define function(TYPE, NAME, VALUE) PrynResultFunction##TYPE##NAME = PrynResultSource##TYPE | ((VALUE) << PrynResultFunctionShift)

	function (Pin, CanConnect, 0), ///< Function code for #prynPinCanConnect.
	function (Pin, ChangeValue, 1), ///< Function code for #prynPinChangeValue.
	function (Pin, Component, 2), ///< Function code for #prynPinComponent.
	function (Pin, Connect, 3), ///< Function code for #prynPinConnect.
	function (Pin, Connected, 4), ///< Function code for #prynPinConnected.
	function (Pin, Create, 5), ///< Function code for #prynPinCreate.
	function (Pin, Destroy, 6), ///< Function code for #prynPinDestroy.
	function (Pin, Disconnect, 7), ///< Function code for #prynPinDisconnect.
	function (Pin, IsConnected, 8), ///< Function code for #prynPinIsConnected.
	function (Pin, IsFirst, 9), ///< Function code for #prynPinIsFirst.
	function (Pin, IsInput, 10), ///< Function code for #prynPinIsInput.
	function (Pin, IsLast, 11), ///< Function code for #prynPinIsLast.
	function (Pin, IsOutput, 12), ///< Function code for #prynPinIsOutput.
	function (Pin, List, 13), ///< Function code for #prynPinList.
	function (Pin, ListCount, 14), ///< Function code for #prynPinListCount.
	function (Pin, Next, 15), ///< Function code for #prynPinNext.
	function (Pin, Previous, 16), ///< Function code for #prynPinPrevious.
	function (Pin, SetType, 17), ///< Function code for #prynPinSetType.
	function (Pin, SetValue, 18), ///< Function code for #prynPinSetValue.
	function (Pin, State, 19), ///< Function code for #prynPinState.
	function (Pin, Tags, 20), ///< Function code for #prynPinTags.
	function (Pin, ToObject, 21), ///< Function code for #prynPinToObject.
	function (Pin, Value, 22), ///< Function code for #prynPinValue.
	// next value: 23

	#undef function

	PrynResultMaximum = 3, ///< Maximum defined positive value for a result (and next available success code).
	PrynResultMinimum = -12, ///< Minimum defined negative value for a result (and next available error code).
};

/// Create a result code by combining the code with the function. Both are suffixes.
#define prynResultCreate(CODE, FUNCTION) (PrynResult##CODE | PrynResultFunction##FUNCTION)

#define prynResultCode(RESULT) ((RESULT) & PrynResultCodeMask) ///< Isolate the code part of a result.
#define prynResultSource(RESULT) ((RESULT) & PrynResultSourceMask) ///< Isolate the source part of a result.
#define prynResultFunction(RESULT) ((RESULT) & PrynResultFunctionMask) ///< Isolate the function part of a result, identifying the function in the source.
#define prynResultSourceFunction(RESULT) ((RESULT) & PrynResultSourceFunctionMask) ///< Isolate the source and function parts of the result, identifying the function globally.
#define prynResultSourceIsGeneral(RESULT) (prynResultSource (RESULT) == PrynResultSourceGeneral) ///< Whether the result value's source is general, as in not assigned to any specific slot.
#define prynResultFunctionIsGeneral(RESULT) (prynResultFunction (RESULT) == PrynResultFunctionGeneral) ///< Whether the result value's function is general, as in not assigned to any specific slot.

/// This is an exception thrown from a Pryn function in C++. It is visible in C but has no purpose.
struct PrynException
{
	struct PrynState *state; ///< State where the exception is from.
	PrynResult result; ///< Result code that caused the exception.

#if __cplusplus
	inline PrynException (PrynState *state, PrynResult result) : state (state), result (result) { }
		///< Set the result parameter.
#endif /* __cplusplus */
};

struct PrynString;

PrynImport (PrynResult, prynResultSourceName, (PrynResult value, struct PrynString *output)) ///< Retrieve the name of the source in code name, such as "PrynChange".

#endif /* PRYN_RESULT_H */
